/*
 * Copyright 2011 Katsunori Koyanagi
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package sweezy.core.utils
{
	import flash.utils.Dictionary;
	import flash.utils.describeType;

	public class Constant
	{

		private static var _nameMaps:Dictionary = new Dictionary(true);

		private static var _valueMaps:Dictionary = new Dictionary(true);

		public static function getAsObject(target:Class):Object
		{
			var result:Object = {};

			if (target === null)
			{
				return result;
			}
			if (!(target in _nameMaps))
			{
				init(target);
			}

			var nameMap:Object = _nameMaps[target];
			for (var name:String in nameMap)
			{
				result[name] = nameMap[name];
			}

			return result;
		}

		public static function getName(target:Class, value:*):String
		{
			if (target === null)
			{
				return null;
			}

			if (!(target in _valueMaps))
			{
				init(target);
			}

			var valueMap:Object = _valueMaps[target];
			return valueMap[value];
		}

		public static function getNames(target:Class):Array
		{
			var result:Array = [];

			if (target === null)
			{
				return result;
			}

			if (!(target in _nameMaps))
			{
				init(target);
			}

			var index:uint = 0;
			for (var name:String in _nameMaps[target])
			{
				result[index++] = name;
			}

			return result;
		}

		public static function getValue(target:Class, name:String):*
		{
			if (target === null)
			{
				return null;
			}

			if (!(target in _nameMaps))
			{
				init(target);
			}

			var nameMap:Object = _nameMaps[target];
			return nameMap[name];
		}

		public static function getValues(target:Class):Array
		{
			var result:Array = [];

			if (target === null)
			{
				return result;
			}

			if (!(target in _valueMaps))
			{
				init(target);
			}

			var index:uint = 0;
			for (var name:String in _valueMaps[target])
			{
				result[index++] = name;
			}

			return result;
		}

		public static function hasName(target:Class, name:String):Boolean
		{
			if (target === null)
			{
				return false;
			}

			if (!(target in _nameMaps))
			{
				init(target);
			}

			return name in _nameMaps[target];
		}

		public static function hasValue(target:Class, value:*):Boolean
		{
			if (target === null)
			{
				return false;
			}

			if (!(target in _valueMaps))
			{
				init(target);
			}

			return value in _valueMaps[target];
		}

		protected static function init(target:Class):void
		{
			if (!(target in _nameMaps))
			{
				_nameMaps[target] = {};
				_valueMaps[target] = {};
			}
			var nameMap:Object = _nameMaps[target];
			var valueMap:Object = _valueMaps[target];

			for each (var constant:XML in describeType(target).constant)
			{
				var name:String = constant.@name;
				var value:* = target[name];
				nameMap[name] = value;
				valueMap[value] = name;
			}
		}
	}
}
